/*
 * SyncResource.java
 *
 * Created on April 12, 2007, 1:39 PM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */

package org.atomojo.app.admin;

import java.io.File;
import java.io.IOException;
import java.util.logging.Level;
import org.atomojo.app.App;
import org.atomojo.app.Storage;
import org.atomojo.app.auth.User;
import org.atomojo.app.client.XMLRepresentationParser;
import org.atomojo.app.db.DB;
import org.atomojo.app.db.RemoteApp;
import org.atomojo.app.db.SyncProcess;
import org.atomojo.app.db.SyncTarget;
import org.atomojo.app.sync.PullSynchronizer;
import org.atomojo.app.sync.SyncException;
import org.infoset.xml.Document;
import org.infoset.xml.Element;
import org.infoset.xml.XMLException;
import org.infoset.xml.util.DocumentDestination;
import org.restlet.data.MediaType;
import org.restlet.data.Status;
import org.restlet.representation.Representation;
import org.restlet.representation.StringRepresentation;
import org.restlet.representation.Variant;
import org.restlet.resource.ServerResource;

/**
 *
 * @author alex
 */
public class RestoreResource extends ServerResource implements AdminXML
{
   
   /** Creates a new instance of SyncResource */
   public RestoreResource() {
      setNegotiated(false);
   }
   
   public Representation get()
   {
      getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
      return null;
   }
   
   public Representation post(Representation entity)
   {
      if (!XMLRepresentationParser.isXML(entity.getMediaType())) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("Non-XML media type for entity body: "+entity.getMediaType().getName());
      }
      
      final DB db = (DB)getRequest().getAttributes().get(App.DB_ATTR);
      final Storage storage = (Storage)getRequest().getAttributes().get(App.STORAGE_ATTR);
      XMLRepresentationParser parser = new XMLRepresentationParser();
      try {
         DocumentDestination dest = new DocumentDestination();
         
         parser.parse(entity,AdminApplication.createAdminDocumentDestination(dest,AdminXML.NM_RESTORE));
         Document doc = dest.getDocument();
         
         Element top = doc.getDocumentElement();
         String location = top.getAttributeValue("location");
         if (location!=null) {
            location = location.trim();
            if (location.length()==0) {
               location = null;
            }
         }
         Element appE = top.getFirstElementNamed(AdminXML.NM_APP);
         if (location==null && appE==null) {
            getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
            return new StringRepresentation("A location or remote app is required.");
         }

         RemoteApp app = null;
         if (location==null) {
            app = new RemoteApp(db,appE);
            app.unmarshall();
            if (!app.getIntrospection().isAbsolute()) {
               getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
               return new StringRepresentation("URI could not be resolved to absolute URI: "+appE.getAttributeValue("introspect"));
            }
         } else {
            File dir = new File(location);
            if (!dir.exists()) {
               getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
               return new StringRepresentation("The "+dir.getAbsolutePath()+" doesn't exist.");
            }
            if (!dir.canRead()) {
               getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
               return new StringRepresentation("Cannot write to "+dir.getAbsolutePath());
            }
            File introspect = new File(dir,"_introspection_.xml");
            if (!introspect.exists()) {
               getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
               return new StringRepresentation("Introspection document "+introspect.getAbsolutePath()+" does not exist.");
            }
            
            app = new RemoteApp(db,"backup");
            app.setIntrospection(introspect.toURI());
            app.setRoot(dir.toURI());
         }
         
         SyncTarget target = new SyncTarget(db,"");
         
         SyncProcess proc = new SyncProcess(db,"restore",true,target,app,null);
         
         User user = (User)getRequest().getAttributes().get(App.USER_ATTR);
         
         try {
            PullSynchronizer restore = new PullSynchronizer(getContext().getLogger(),getApplication().getMetadataService(),user,db,storage,proc);
            restore.setAdditive(false);
            restore.sync();
            if (restore.getErrorCount()>0) {
               getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
               return new StringRepresentation("There were "+restore.getErrorCount()+" errors.  See the log for details.");
            } else {
               getResponse().setStatus(Status.SUCCESS_NO_CONTENT);
               return null;
            }
         } catch (SyncException ex) {
            getContext().getLogger().log(Level.SEVERE,"Cannot perform restore to due to: "+ex.getMessage(),ex);
            getResponse().setStatus(Status.SERVER_ERROR_INTERNAL);
            return new StringRepresentation("Cannot perform restore to due to: "+ex.getMessage());
         }
         
      } catch (IOException ex) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("I/O exception: "+ex.getMessage());
      } catch (XMLException ex) {
         getResponse().setStatus(Status.CLIENT_ERROR_BAD_REQUEST);
         return new StringRepresentation("XML exception: "+ex.getMessage());
      }
   }
   
}
